package com.talkweb.platform.commonapi.utils;

import java.io.UnsupportedEncodingException;
import java.math.BigInteger;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Map;
import java.util.Random;


/**
 * 对数据进行MD5加密;
 * 
 * @author lzy
 */
public class MD5Encrypt {
	private static final String HEX_NUMS_STR = "0123456789ABCDEF";

	private static final Integer SALT_LENGTH = 12;

	/**
	 * 加密过程(接受用户输入的密码信息,进行加密并返回);
	 * 
	 * @throws NoSuchAlgorithmException
	 * @throws UnsupportedEncodingException
	 */
	public static String getEncryptedPwd(String info) {
		String pwd = null;
		// 1.获得随机盐数据;
		Random rand = new Random();
		byte[] salt = new byte[SALT_LENGTH];
		rand.nextBytes(salt);

		// 2.更新摘要信息,并加密后返回byte[]数组;
		try {
			MessageDigest messageDigest = MessageDigest.getInstance("MD5");
			messageDigest.update(salt);
			messageDigest.update(info.getBytes("UTF-8"));
			byte[] dig = messageDigest.digest();
			// 创建一个新的数组将盐数据和最终摘要信息进行保存(前12位保存盐,后16位保存最终摘要信息);
			byte[] pwdArray = new byte[salt.length + dig.length];
			System.arraycopy(salt, 0, pwdArray, 0, salt.length);
			System.arraycopy(dig, 0, pwdArray, salt.length, dig.length);
			// 将此最终数组转换成String字符类型;
			pwd = byteToHexString(pwdArray);
		} catch (Exception e) {
			e.printStackTrace();
		}

		return pwd;
	}

	/**
	 * md5加密函数(bpm老方法)
	 * 
	 * @param str
	 * @return
	 */
	public static String md5(String str) {
		String re_md5 = new String();
		try {
			MessageDigest md = MessageDigest.getInstance("MD5");
			md.update(str.getBytes());
			byte b[] = md.digest();
			int i;
			StringBuffer buf = new StringBuffer("");
			for (int offset = 0; offset < b.length; offset++) {
				i = b[offset];
				if (i < 0)
					i += 256;
				if (i < 16)
					buf.append("0");
				buf.append(Integer.toHexString(i));
			}
			re_md5 = buf.toString();
		} catch (Exception e) {
			e.printStackTrace();
		}
		return re_md5;
	}
	/**
	 * 解密过程(仍然是接受用户输入的信息,同时接受第二个数据【数据库中加密的String字符】);
	 * 
	 * @throws NoSuchAlgorithmException
	 */
	public static boolean validPassword(String data, String pwd) throws Exception {
		boolean flag = false;
		// 将从数据库中获得数据转换成16位byte[]数组;
		byte[] pwdArray = hexStringToByte(data);
		// 创建盐数组,同时为盐数组copy数据;
		byte[] salt = new byte[SALT_LENGTH];
		System.arraycopy(pwdArray, 0, salt, 0, salt.length);
		// 将用户输入的信息与获取的盐数据再次进行加密;
		MessageDigest m = MessageDigest.getInstance("MD5");
		m.update(salt);
		m.update(pwd.getBytes("UTF-8"));
		byte[] newArray = m.digest();
		// 再次copy数组;
		byte[] infoArray = new byte[salt.length + newArray.length];
		System.arraycopy(salt, 0, infoArray, 0, salt.length);
		System.arraycopy(newArray, 0, infoArray, salt.length, newArray.length);
		// 将最终byte[]数组转换为String字符类型;
		String info = byteToHexString(infoArray);
		if (info.equals(data)) {
			flag = true;
		}

		return flag;
	}

	/**
	 * 将16进制字符串转换成字节数组
	 * 
	 * @param hex
	 * @return
	 */
	public static byte[] hexStringToByte(String hex) {
		int len = (hex.length() / 2);
		byte[] result = new byte[len];
		char[] hexChars = hex.toCharArray();
		for (int i = 0; i < len; i++) {
			int pos = i * 2;
			result[i] = (byte) (HEX_NUMS_STR.indexOf(hexChars[pos]) << 4 | HEX_NUMS_STR.indexOf(hexChars[pos + 1]));
		}
		return result;
	}

	/**
	 * 将指定byte数组转换成16进制字符串
	 * 
	 * @param b
	 * @return
	 */
	public static String byteToHexString(byte[] b) {
		StringBuffer hexString = new StringBuffer();
		for (int i = 0; i < b.length; i++) {
			String hex = Integer.toHexString(b[i] & 0xFF);
			if (hex.length() == 1) {
				hex = '0' + hex;
			}
			hexString.append(hex.toLowerCase());
		}
		return hexString.toString();
	}
	
	public static String encrypt(String info) {
        String pwd = null;
        try {
            MessageDigest messageDigest = MessageDigest.getInstance("MD5");
            messageDigest.update(info.getBytes("UTF-8"));
            pwd = byteToHexString(messageDigest.digest());
        } catch (Exception e) {
            e.printStackTrace();
        }
        return pwd;
    }
	
	public static String digest(Map<String, String> map) {
	        MessageDigest digest = null;
	        try {
	            digest = MessageDigest.getInstance("MD5");
	        } catch (NoSuchAlgorithmException e) {
	            throw new IllegalStateException("MD5 algorithm not available.  Fatal (should be in the JDK).");
	        }

	        try {
	            byte[] bytes = digest.digest(map.toString().getBytes("UTF-8"));
	            String result = String.format("%032x", new BigInteger(1, bytes));
	            return result.substring(8, 24);
	        } catch (UnsupportedEncodingException e) {
	            throw new IllegalStateException("UTF-8 encoding not available.  Fatal (should be in the JDK).");
	        }
	    }
}
